#include <QDebug>
#include <QRegularExpression>
#include "mgapp.hpp"


SerialManage *SerialManage::instance = nullptr;

SerialManage::SerialManage() {
    timer.setInterval(1000);
    connect(&timer, &QTimer::timeout, this, &SerialManage::onUpdateList);
    timer.start();
}

SerialManage::~SerialManage() {
    timer.stop();
}

SerialManage *SerialManage::getInstance() {
    if (instance == nullptr) {
        instance = new SerialManage();

    }
    return instance;
}

void SerialManage::onUpdateList() {
    auto serialList = QSerialPortInfo::availablePorts();
    QList<QString> names;
    bool update = false;
    for (const auto& serial: serialList) {
        QString name = serial.portName();
        names.append(name);
        if (!serials.contains(name)) {
            update = true;
        }
    }

    for (const auto& name: serials) {
        if (!names.contains(name)) {
            update = true;
        }
    }

    if (update) {
        serials = names;
        emit listChanged(names);
    }
}


static const uint8_t aucCRCHi[] =
    {
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40
};

static const uint8_t aucCRCLo[] =
    {
        0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
        0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
        0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
        0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
        0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
        0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
        0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
        0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
        0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
        0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
        0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
        0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
        0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
        0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
        0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
        0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
        0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
        0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
        0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
        0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
        0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
        0x41, 0x81, 0x80, 0x40
};

static uint16_t cal_crc16(uint8_t *buf, uint16_t len)
{
    uint8_t ucCRCHi = 0xFF;
    uint8_t ucCRCLo = 0xFF;
    int iIndex;

    while(len--)
    {
        iIndex = ucCRCLo ^ *(buf++);
        ucCRCLo = (uint8_t)(ucCRCHi ^ aucCRCHi[iIndex]);
        ucCRCHi = aucCRCLo[iIndex];
    }

    return (uint16_t)(ucCRCHi << 8 | ucCRCLo);
}

static void cal_crc16_to(uint8_t *buf, uint16_t len, uint8_t *crc)
{

    uint16_t data =  cal_crc16(buf, len);
    crc[0] = (data) & 0xFF;
    crc[1] = (data >> 8) & 0xFF;
}


MGApp::MGApp(QObject *parent)
    : QObject{parent}
{
    config = new QSettings("config.ini",QSettings::IniFormat);
    protocol = config->value("protocol", 0).toInt();
    device = config->value("device", "COM0").toString();
    baud = config->value("baud", 115200).toInt();
    parity = config->value("parity", 0).toInt();
    dataBit =config->value("dataBit", 8).toInt();
    stopBit = config->value("stopBit", 1).toInt();
    ip = config->value("ip", "127.0.0.1").toString();
    port = config->value("port", 502).toUInt();


    serialList.append("关闭");
    auto *serialManage = SerialManage::getInstance();
    connect(serialManage, &SerialManage::listChanged, this, [&](QList<QString> &serials) {
        serialList.clear();
        serialList.append("关闭");
        for (int i = serials.size() - 1; i >= 0; i--) {
            serialList.append(serials[i]);
        }
        emit serialListChanged();
    });
    connect(&serial,&QSerialPort::readyRead, this, &MGApp::onReadyRead);
    connect(&tcpSocket,&QTcpSocket::readyRead, this, &MGApp::onReadyRead);
    connect(&tcpSocket,&QTcpSocket::connected, this, [&]{
        linkStatus = true;
        emit linkStatusChanged();
    });
    connect(&tcpSocket,&QTcpSocket::disconnected, this, [&]{
        linkStatus = false;
        emit linkStatusChanged();
    });
    connect(&udpSocket,&QUdpSocket::readyRead, this, &MGApp::onReadyRead);
    connect(&udpSocket,&QUdpSocket::connected, this, [&]{
        linkStatus = true;
        emit linkStatusChanged();
    });
    connect(&udpSocket,&QUdpSocket::disconnected, this, [&]{
        linkStatus = false;
        emit linkStatusChanged();
    });
}

MGApp::~MGApp()
{
    config->setValue("protocol", protocol);
    config->setValue("device", device);
    config->setValue("baud", baud);
    config->setValue("parity", parity);
    config->setValue("dataBit", dataBit);
    config->setValue("stopBit",stopBit);
    config->setValue("ip", ip);
    config->setValue("port", port);
    config->sync();
    delete config;
}

void MGApp::openSerial()
{
    if (protocol == 0){

        if (device != "关闭"){
        if (serial.isOpen()){
            serial.close();
            linkStatus = false;
            emit linkStatusChanged();
        }
        serial.setPortName(device);
        linkStatus = serial.open(QIODevice::ReadWrite);
        emit linkStatusChanged();
        serial.setBaudRate(baud);
        onDataBitChanged();
        onParityChanged();
        onStopBitChanged();
        serial.setFlowControl(QSerialPort::NoFlowControl);
        }
    }else if(protocol == 1){
        if(tcpSocket.state()==QAbstractSocket::ConnectedState){
            tcpSocket.abort();
        }
        tcpSocket.connectToHost(ip, port);
    }else if(protocol == 2){
        if(udpSocket.state()==QAbstractSocket::ConnectedState){
            udpSocket.abort();
        }
        udpSocket.connectToHost(ip, port);
    }
}

void MGApp::closeSerial()
{
    if (protocol == 0){
        if (serial.isOpen()){
            serial.close();
        }
    }else if(protocol == 1){
        if(tcpSocket.state()==QAbstractSocket::ConnectedState){
            tcpSocket.abort();
        }
    }else if(protocol == 2){
        if(udpSocket.state()==QAbstractSocket::ConnectedState){
            udpSocket.abort();
        }
    }
    linkStatus = false;
    emit linkStatusChanged();
}



void MGApp::onBaudChanged()
{
    if (!linkStatus) return;
    serial.setBaudRate(baud);
}

void MGApp::onParityChanged()
{
    if (!linkStatus) return;
    switch (dataBit) {
    case 0:
        case 'N':
        case 'n':
        serial.setParity(QSerialPort::NoParity);
        break;
    case 1:
        case 'E':
        case 'e':
        serial.setParity(QSerialPort::EvenParity);
        break;
    case 2:
        case 'O':
        case 'o':
        serial.setParity(QSerialPort::OddParity);
        break;
    case 3:
        serial.setParity(QSerialPort::SpaceParity);
        break;
    case 4:
        serial.setParity(QSerialPort::MarkParity);
        break;
    default:
        break;
    }
}

void MGApp::onDataBitChanged()
{
    if (!linkStatus) return;
    switch (dataBit) {
    case 5:
        serial.setDataBits(QSerialPort::Data5);
        break;
    case 6:
        serial.setDataBits(QSerialPort::Data6);
        break;
    case 7:
        serial.setDataBits(QSerialPort::Data7);
        break;
    case 8:
        serial.setDataBits(QSerialPort::Data8);
        break;
    default:
        break;
    }
}

void MGApp::onStopBitChanged()
{
    if (!linkStatus) return;
    switch (stopBit) {
    case 1:
        serial.setStopBits(QSerialPort::OneStop);
        break;
    case 2:
        serial.setStopBits(QSerialPort::TwoStop);
        break;
    case 3:
        serial.setStopBits(QSerialPort::OneAndHalfStop);
        break;
    default:
        break;
    }

}


QString MGApp::toUpper(const QString &str)
{
    int len = str.length();
    auto placeholder = str.toStdString();
    const char *p = placeholder.c_str();
    char *buf = new char[len+1];
    for (int i = 0; i < len; i++){
        if (p[i] >= '0' && p[i] < '9'){
            buf[i] = p[i];
        }else if (p[i] >= 'a' && p[i] <= 'z'){
            if (p[i] != 'x'){
                buf[i] = p[i] - 'a' + 'A';
            }else{
                buf[i] = p[i];
            }
        }else{
            buf[i] = p[i];
            if (buf[i] == 'X'){
                buf[i] = 'x';
            }
        }
    }
    buf[len] = 0;
    auto ret = QString(buf);
    delete[] buf;
    return ret;
}

static uint16_t to16Short(QString &str){
    uint16_t ret = 0;
    int len = str.length();
    auto placeholder = str.toStdString();
    const char *p = placeholder.c_str();
    for (int i = 0; i < len; i++){
        if (p[i] > '9'){
            ret = ret * 16 + (p[i] - 'A' + 10);
        }else{
            ret = ret * 16 + (p[i] - '0');
        }
    }
    return ret;
}

static uint16_t to10Short(QString &str){
    uint16_t ret = 0;
    int len = str.length();
    auto placeholder = str.toStdString();
    const char *p = placeholder.c_str();
    for (int i = 0; i < len; i++){
            ret = ret * 10 + (p[i] - '0');
    }
    return ret;
}

static uint16_t toNum2(QString &str){
    uint16_t ret = 0;
    if (str.isEmpty()) return ret;
    int len = str.length();
    auto placeholder = str.toStdString();
    const char *p = placeholder.c_str();
    bool is16hex = false;
    int idx = 0;
    char *buf = new char[len+1];
    for (int i = 0; i < len; i++){
        if (p[i] > '9'){
            is16hex = true;
        }
        if ((p[i] >= '0' && p[i] <= '9') || (p[i] >= 'A' && p[i] <= 'F')){
            buf[idx] = p[i];
            idx++;
        }
    }
    buf[idx] = 0;
    if (is16hex){
        auto str = QString(buf);
        ret = to16Short(str);
    }else{
        auto str = QString(buf);
        ret = to10Short(str);
    }
    delete[] buf;
    return ret;
}

static int toNum3(QString &str,uint8_t *outBuf){
    int outIdx = 0;
    uint32_t temp = 0;
    auto strlist = str.split(" ");
    for (int k = 0; k < strlist.length(); k++){
        temp = 0;
        auto s = strlist[k];
        if (s.isEmpty()) continue;
        int len = s.length();
        auto placeholder = s.toStdString();
        const uint8_t *p = (const uint8_t *)placeholder.c_str();
        bool is16hex = false;
        int idx = 0;
        uint8_t *buf = new uint8_t[len+1];
        for (int i = 0; i < len; i++){
            if (p[i] > '9'){
                is16hex = true;
            }
            if ((p[i] >= '0' && p[i] <= '9') || (p[i] >= 'A' && p[i] <= 'F')){
                buf[idx] = p[i];
                idx++;
            }
        }
        buf[idx] = 0;
        len  = idx;
        p = buf;
        int startIdx = outIdx;
        uint32_t sk = 1;
        for (int i = len - 1; i >= 0; i--){
            if (is16hex){
                if (p[i] > '9'){
                    temp = temp + (p[i] - 'A' + 10) * sk;
                }else{
                    temp = temp + (p[i] - '0') * sk;
                }
                sk *= 16;
            }else{
                temp = temp + (p[i] - '0') * sk;
                sk *= 10;
            }

            if (temp > 0xFFFF){
                    outBuf[outIdx] = (temp >> 8) & 0xFF;
                    outBuf[outIdx + 1] = temp & 0xFF;
                    outIdx+=2;
                    temp = temp >> 16;
                    if (is16hex){
                        sk = 16;
                    }else{
                        sk = 10;
                    }
            }
            outBuf[outIdx ] = (temp >> 8) & 0xFF;
            outBuf[outIdx+ 1] = temp & 0xFF;

        }
        outIdx+=2;
        int u16len = (outIdx - startIdx) / 2;
        uint8_t *p1 = outBuf + startIdx;
        uint8_t *p2 = outBuf + outIdx - 2;
        for (int i = 0; i < u16len / 2; i++){
            uint8_t d1,d2;
            d1 = p1[0];
            d2 = p1[1];
            p1[0] = p2[0];
            p1[1] = p2[1];
            p2[0] = d1;
            p2[1] = d2;
            p1+=2;
            p2-=2;
        }
        delete[] buf;

    }
    return outIdx;
}

static int toNum4(QString &str,uint8_t *outBuf){
    int outIdx = 0;
    uint32_t temp = 0;
    auto strlist = str.split(" ");
    for (int k = 0; k < strlist.length(); k++){
        temp = 0;
        auto s = strlist[k];
        if (s.isEmpty()) continue;
        int len = s.length();
        auto placeholder = s.toStdString();
        const uint8_t *p = (const uint8_t *)placeholder.c_str();
        bool is16hex = false;
        int idx = 0;
        uint8_t *buf = new uint8_t[len+1];
        for (int i = 0; i < len; i++){
            if (p[i] > '9'){
                    is16hex = true;
            }
            if ((p[i] >= '0' && p[i] <= '9') || (p[i] >= 'A' && p[i] <= 'F')){
                    buf[idx] = p[i];
                    idx++;
            }
        }

        buf[idx] = 0;
        len  = idx;
        p = buf;
        for (int i = 0; i < len; i++){
            if (is16hex){
                    if (p[i] > '9'){
                        temp = temp * 16 + (p[i] - 'A' + 10);
                    }else{
                        temp = temp * 16 + (p[i] - '0');
                    }
            }else{
                    temp = temp * 10 + (p[i] - '0');
            }

            if (temp > 0xFF){
                    outBuf[outIdx] = temp & 0xFF;
                    outIdx+=1;
                    temp = temp >> 8;
            }
            outBuf[outIdx] = temp & 0xFF;

        }
        outIdx+=1;
        delete[] buf;

    }
    return outIdx;
}

static QString toHexStr(uint8_t *buf, int len){
    if (len == 0) return {""};
    char *str = new char[len*3];
    for (int i = 0; i < len; i++){
        uchar k = buf[i] >> 4 & 0xF;
        if (k > 9){
            str[i * 3] = k - 10 + 'A';
        }else{
            str[i * 3] = k + '0';
        }
        k = buf[i] & 0xF;
        if (k > 9){
            str[i * 3 + 1] = k - 10 + 'A';
        }else{
             str[i * 3 + 1] = k + '0';
        }
        str[i * 3 + 2] = ' ';
    }
    str[len * 3-1] = 0;
    QString ret(str);
    delete[] str;
    return ret;
}

//static bool IsIp(QString &currentIp)
//{
//    auto ip = currentIp.split(".");
//    if (ip.length() != 4) return false;
//    for (int i = 0; i < 4; i++){
//        auto s = ip[i];
//        if (a < 0 || a > 255){
//             return false;
//        }
//    }
//    return true;
//}

QString MGApp::sendData(int code, QString slaveStr, QString regStr, QString lenStr, QString varStr, QString regStr2)
{
    QString retStr = "";
    uint8_t slave = toNum2(slaveStr) % 256;
    uint16_t reg = toNum2(regStr);
    uint16_t len = toNum2(lenStr);
    uint8_t *p1;
    uint8_t *p2;
    uint8_t framebuf[256+32];
    uint8_t *buf = framebuf;
    int buflen = 0;
    int preidx = 0;

    if (protocol == 1 || protocol == 2){
        buf[0] = mbapId >> 8;
        buf[1] = mbapId & 0xFF;
        buf[2] = 0;
        buf[3] = 0;
        buf[4] = 0;
        buf[5] = 0;
        preidx = 6;
        buf+=preidx;
        mbapId++;
        emit mbapIdChanged();
    }
    buf[0] = slave;
    buf[1] = code;
    buf[2] = reg  >> 8;
    buf[3] = reg  & 0xFF;
    buflen = 4;
    int idx = 0;

    switch (code) {
    case 0x01:
    case 0x02:
    case 0x03:
    case 0x04:
        buf[4] = len  >> 8;
        buf[5] = len  & 0xFF;
        buflen += 2;
        cal_crc16_to(buf, buflen,buf+buflen);
        buflen += 2;
        break;
    case 0x05:
    case 0x06:
        buf[4] = 0;
        buf[5] = 0;
        idx = toNum3(varStr, buf+buflen);
        buflen += idx;
        cal_crc16_to(buf, buflen,buf+buflen);
        buflen += 2;
        break;
    case 0x0F:
        buf[4] = (len >> 8) & 0xFF;
        buf[5] = len & 0xFF;
        buf[6] = len / 8 + ((len % 8) ? 1 : 0);
        buflen += 3;
        idx = toNum3(varStr, buf+buflen);
        len = buf[6];
        if (idx > len){
              p1 = (uint8_t*)(buf+buflen);
             p2 =  (uint8_t*)(buf+buflen + (idx - len));
              for (int i = 0; i < len; i++){
                    p1[i] = p2[i];
                }
        }else if (idx < len){
            p1 = (buf+buflen + len);
            p2 = (buf+buflen +idx);
            for (int i = idx-1; i >= 0; i--){
                p1[i] = p2[i];
            }
            p1 = (uint8_t*)(buf+buflen);
            for (int i = 0; i < (len -idx); i++){
                p1[i] = 0;
            }
        }
        buflen += len;
        cal_crc16_to(buf, buflen,buf+buflen);
        buflen += 2;
        break;
    case 0x10:
        buflen += 3;
        idx = toNum3(varStr, buf+buflen);
        buf[4] = (idx / 2 >> 8) & 0xFF;
        buf[5] = idx / 2 & 0xFF;
        buf[6] = idx;
        buflen += idx;
        cal_crc16_to(buf, buflen,buf+buflen);
        buflen += 2;
        break;
    case 0x09:
        reg = toNum2(regStr2);
        buf[4] = len  >> 8;
        buf[5] = len  & 0xFF;
        buf[6] = reg  >> 8;
        buf[7] = reg  & 0xFF;
        buflen += 7;
        idx = toNum3(varStr, buf+buflen);
        buf[8] = (idx / 2 >> 8) & 0xFF;
        buf[9] = idx / 2 & 0xFF;
        buf[10] = idx;
        buflen += idx;
        cal_crc16_to(buf, buflen,buf+buflen);
        buflen += 2;
        break;
    case 0x00:
        buflen = toNum4(varStr, buf);
        if (regStr2 == "1"){
             cal_crc16_to(buf, buflen,buf+buflen);
             buflen += 2;
        }
        break;
    default:
        break;
    }

    qint64 ok = 0;
    if (linkStatus){
        startTime = std::chrono::system_clock::now();
        if (protocol == 0){
            ok = serial.write((char*)framebuf, buflen+ preidx);
             serial.flush();
        }else if (protocol == 1){
             buflen -= 2;
             framebuf[4] = (buflen) >> 8;
             framebuf[5] = (buflen) & 0xFF;
            ok = tcpSocket.write((char*)framebuf, buflen + preidx);
            tcpSocket.flush();
        }else if (protocol == 2){
            buflen -= 2;
            framebuf[4] = (buflen) >> 8;
            framebuf[5] = (buflen) & 0xFF;
            ok = udpSocket.write((char*)framebuf, buflen + preidx);
            udpSocket.flush();
        }
        if(ok){
             sendframeNum++;
             sendByteNum+=ok;
             emit sendByteNumChanged();
             emit sendframeNumChanged();
        }
    }
    retStr = toHexStr(framebuf, buflen+ preidx);
    emit sendDataChanged(retStr);
    return retStr;
}

void MGApp::onReadyRead()
{
    endTime = std::chrono::system_clock::now();
    responseTime = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
    emit responseTimeChanged();
    uint8_t framebuf[256+32];
    uint8_t *buf = framebuf;
    int recvlen = 0;
    int len = 0;
    if (protocol == 0){
        recvlen = serial.read((char*)framebuf, 256+16);
        len = recvlen;
    }else if (protocol == 1){
        recvlen = tcpSocket.read((char*)framebuf, 256+32);
        if (recvlen >6){
        buf+=6;
        len +=6;
        }
    }else if (protocol == 2){
        recvlen = udpSocket.read((char*)framebuf, 256+32);
        if (recvlen >6){
        buf+=6;
        len +=6;
        }
    }
    auto retStr = toHexStr(framebuf, recvlen);
    emit recvDataChanged(retStr);
    QString retStr2;
    recvframeNum++;
    recvByteNum+=len;
    emit recvByteNumChanged();
    emit recvframeNumChanged();
    switch (buf[1]) {
    case 0x01:
    case 0x02:
    case 0x03:
    case 0x04:
        if (len >=6){
            retStr2 = toHexStr(buf+3 , len - 5);
            emit recvData(buf[1], retStr2);
        }
        break;
    default:
        break;
    }

}

